package v1

import (
	"strconv"

	"wms/internal/model/request"
	"wms/internal/service"
	"wms/pkg/common"
	"wms/pkg/logger"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// MenuController 菜单控制器
type MenuController struct {
	menuService *service.MenuService
}

// NewMenuController 创建菜单控制器
func NewMenuController() *MenuController {
	return &MenuController{
		menuService: service.NewMenuService(),
	}
}

// List godoc
// @Summary 获取菜单列表
// @Description 获取菜单列表，支持分页和搜索
// @Tags 菜单管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param status query int false "菜单状态(1:正常 0:禁用)"
// @Param title query string false "菜单名称"
// @Param path query string false "菜单路径"
// @Param page query int false "页码" default(1)
// @Param size query int false "每页数量" default(10)
// @Success 200 {object} common.Response{data=response.MenuListResponse} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /menus [get]
func (c *MenuController) List(ctx *gin.Context) {
	var req request.MenuListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定菜单列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	menus, err := c.menuService.List(req)
	if err != nil {
		logger.Error("获取菜单列表失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	logger.Info("获取菜单列表成功", zap.Int64("total", menus.Total))
	common.Success(ctx, menus)
}

// GetUserMenus godoc
// @Summary 获取用户菜单
// @Description 获取当前登录用户的菜单权限列表
// @Tags 菜单管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param user_id query int false "用户ID(为空则获取当前用户)"
// @Success 200 {object} common.Response{data=[]response.MenuResponse} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /user/menus [get]
func (c *MenuController) GetUserMenus(ctx *gin.Context) {
	var req request.UserMenusRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定用户菜单请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 如果没有指定用户ID，则获取当前用户ID
	if req.UserID == 0 {
		userID := common.GetUserID(ctx)
		if userID == 0 {
			common.Error(ctx, common.ErrUnauthorized)
			return
		}
		req.UserID = userID
	}

	menus, err := c.menuService.GetUserMenus(req.UserID)
	if err != nil {
		logger.Error("获取用户菜单失败", zap.Error(err), zap.Uint("userID", req.UserID))
		common.Error(ctx, err)
		return
	}

	logger.Info("获取用户菜单成功", zap.Uint("userID", req.UserID))
	common.Success(ctx, gin.H{"list": menus})
}

// Get godoc
// @Summary 获取菜单详情
// @Description 根据ID获取菜单详情
// @Tags 菜单管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "菜单ID"
// @Success 200 {object} common.Response{data=model.Menu} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /menus/{id} [get]
func (c *MenuController) Get(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		logger.Warn("无效的菜单ID", zap.String("id", idStr))
		common.Error(ctx, common.ErrInvalidParams)
		return
	}

	menu, err := c.menuService.GetById(uint(id))
	if err != nil {
		logger.Error("获取菜单详情失败", zap.Error(err), zap.Int("id", id))
		common.Error(ctx, err)
		return
	}

	logger.Info("获取菜单详情成功", zap.Int("id", id))
	common.Success(ctx, menu)
}

// Create godoc
// @Summary 创建菜单
// @Description 创建菜单
// @Tags 菜单管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body request.MenuCreateRequest true "菜单信息"
// @Success 200 {object} common.Response{data=model.Menu} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /menus [post]
func (c *MenuController) Create(ctx *gin.Context) {
	var req request.MenuCreateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定创建菜单请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	menu, err := c.menuService.Create(req)
	if err != nil {
		logger.Error("创建菜单失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	logger.Info("创建菜单成功", zap.Uint("id", menu.ID))
	common.Success(ctx, menu)
}

// Update godoc
// @Summary 更新菜单
// @Description 更新菜单信息
// @Tags 菜单管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "菜单ID"
// @Param request body request.MenuUpdateRequest true "菜单信息"
// @Success 200 {object} common.Response{data=model.Menu} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /menus/{id} [put]
func (c *MenuController) Update(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		logger.Warn("无效的菜单ID", zap.String("id", idStr))
		common.Error(ctx, common.ErrInvalidParams)
		return
	}

	var req request.MenuUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定更新菜单请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}
	req.ID = uint(id)

	menu, err := c.menuService.Update(req)
	if err != nil {
		logger.Error("更新菜单失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	logger.Info("更新菜单成功", zap.Int("id", id))
	common.Success(ctx, menu)
}

// Delete godoc
// @Summary 删除菜单
// @Description 删除菜单
// @Tags 菜单管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "菜单ID"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /menus/{id} [delete]
func (c *MenuController) Delete(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		logger.Warn("无效的菜单ID", zap.String("id", idStr))
		common.Error(ctx, common.ErrInvalidParams)
		return
	}

	if err := c.menuService.Delete(uint(id)); err != nil {
		logger.Error("删除菜单失败", zap.Error(err), zap.Int("id", id))
		common.Error(ctx, err)
		return
	}

	logger.Info("删除菜单成功", zap.Int("id", id))
	common.Success(ctx, nil)
}
